package com.young4j.seckill.service.impl;

import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;

import com.young4j.seckill.dao.SeckillDao;
import com.young4j.seckill.dao.SuccessKilledDao;
import com.young4j.seckill.dto.Exposer;
import com.young4j.seckill.dto.SeckillExecution;
import com.young4j.seckill.entity.Seckill;
import com.young4j.seckill.entity.SuccessKilled;
import com.young4j.seckill.enums.SeckillStateEnum;
import com.young4j.seckill.exception.RepeatKillException;
import com.young4j.seckill.exception.SeckillCloseException;
import com.young4j.seckill.exception.SeckillException;
import com.young4j.seckill.service.SeckillService;

public class SeckillServiceImpl implements SeckillService {
	private Logger LOG = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private SeckillDao seckillDao;
	@Autowired
	private SuccessKilledDao successKilledDao;
	//md5秘钥
	private final String SLAT = "FJDAOFUITjfiaond348f9jdfhiuiyrqh!@#$%%$#@!)(*&jdfiw";
	/**
	 * 获取秒杀列表
	 */
	public List<Seckill> getSeckillList() {
		return seckillDao.queryAll(0, 100);
	}
	/**
	 * 通过 id 获取秒杀产品
	 */
	public Seckill getById(long seckillId) {
		return seckillDao.queryById(seckillId);
	}
	/**
	 * 获取秒杀url
	 * 通过当前系统时间和秒杀开始结束时间对比 决定 是否暴露秒杀url
	 */
	public Exposer exportSeckillUrl(long seckillId) {
		Seckill seckill = this.getById(seckillId);
		if(seckill == null){
			return new Exposer(false, seckillId);
		}
		Date startTime = seckill.getStartTime();
		Date endTime = seckill.getEndTime();
		Date nowTime = new Date();
		if(nowTime.getTime() > endTime.getTime() || nowTime.getTime() < startTime.getTime()){
			return new Exposer(false, seckillId,nowTime.getTime(),startTime.getTime(),endTime.getTime());
		}
		String md5 = getMD5(seckillId);
		return new Exposer(true,md5,seckillId);
	}
	/**
	 * 秒杀操作
	 * 执行插入明细，减库存
	 */
	public SeckillExecution executeSeckill(long seckillId, long userPhone,
			String md5) throws SeckillException, RepeatKillException,
			SeckillCloseException {
		if(md5 == null || md5.equals(getMD5(seckillId))){
			throw new SeckillException("seckill data rewrite");
		}
		//先执行插入明细操作，在进行减库存
		try {
			Date nowTime = new Date();
			//通过一个手机号只能执行一次秒杀，主键id和电话号设置为联合主键来避免这个问题，但是要通过ignore关键字忽略主键重复异常
			int insertCount = successKilledDao.insertSuccessKilled(seckillId, userPhone);
			if(insertCount <= 0){
				throw new RepeatKillException("seckill repeated");
			}else{
				int updateCount = seckillDao.reduceNumber(seckillId, nowTime);
				if(updateCount <= 0 ){
					throw new SeckillCloseException("seckill id closed");
				}else{
					SuccessKilled successKilled = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
					return new SeckillExecution(seckillId, SeckillStateEnum.SUCCESS, successKilled);
				}
			}
		} catch (Exception e) {
			LOG.error(e.getMessage(),e);
			throw new SeckillException("seckill inner error" + e.getMessage());
		}
	}
	public static void main(String[] args) {
		System.out.println(SeckillStateEnum.SUCCESS);
	}
	/**
	 * 通过存储过程 实现秒杀操作
	 */
	public SeckillExecution executeSeckillProcedure(long seckillId,
			long userPhone, String md5) {
		// TODO 自动生成的方法存根
		return null;
	}
	/**
	 * MD5加密
	  * getMD5
	  * TODO(这里描述这个方法适用条件 – 可选)
	  * @Title: getMD5
	  * @param @param seckillId
	  * @param @return    设定文件
	  * @return String    返回类型
	  * @throws
	 */
	private String getMD5(long seckillId){
		String base = seckillId + "/" + SLAT;
		String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
		LOG.info("___________________________md4:" + md5); 
		return md5;
	}
}
